/******************************************************************************
* 文件名  ：DRV_Spi1.c
* 文件描述: for NFC RC522
* 创建人  ：
* 日    期：
* 
* 1. 硬件连接：端口
            PA11 - NFC_NRSTPD
            PA15 - NFC_IRQ
            PA6  - NFC_SPI_MISO
            PA7  - NFC_SPI_MOSI
            PA5  - NFC_SPI_SCK
            PA4  - NFC_CS
  2. NFC连接SPI1          
******************************************************************************/

#include "DRV_Spi1.h"


#define SPI_WAIT_TIMEOUT     (100u)


void SPI2_Config(void);
void SPI2_Deconfig(void);
uint8_t SPI2_WR_Bytes(SPI_TypeDef* SPIx, uint8_t *pdata, uint16_t len);


spi_context_t spi2_context={
    .SPIx      = SPI2,
    .config    = SPI2_Config,
    .deconfig  = SPI2_Deconfig,
    .wr_bytes  = SPI2_WR_Bytes,
};

void SPI2_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;
 
    /* 使能SPI时钟         */
    FLASH_SPI_APBxPeriphClockCmd(FLASH_SPI_CLK, ENABLE);
    
    /* 使能SPI引脚相关时钟 */
    FLASH_SPI_CS_APBxPeriphClockCmd(FLASH_SPI_CS_CLK, ENABLE);
    FLASH_SPI_SCK_APBxPeriphClockCmd(FLASH_SPI_SCK_CLK, ENABLE);
    FLASH_SPI_MISO_APBxPeriphClockCmd(FLASH_SPI_MISO_CLK, ENABLE);
    FLASH_SPI_MOSI_APBxPeriphClockCmd(FLASH_SPI_MOSI_CLK, ENABLE);
    
    /* 配置SPI的 CS引脚，普通IO即可 */
    GPIO_InitStructure.GPIO_Pin   = FLASH_SPI_CS_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);    

    /* 配置SPI的 SCK引脚*/
    GPIO_InitStructure.GPIO_Pin  = FLASH_SPI_SCK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);

    /* 配置SPI的 MISO引脚*/
    GPIO_InitStructure.GPIO_Pin  = FLASH_SPI_MISO_PIN;
    GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStructure);

    /* 配置SPI的 MOSI引脚*/
    GPIO_InitStructure.GPIO_Pin  = FLASH_SPI_MOSI_PIN;
    GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);

    /* 停止信号: CS引脚高电平*/
    FLASH_SPI_CS_HIGH();
  
	/* SPI的基本配置 */
	SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;  // 设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;	                // 设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize          = SPI_DataSize_8b;                  // 设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL              = SPI_CPOL_High;		            // 串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA              = SPI_CPHA_2Edge;	                // 串行同步时钟的第二个跳变沿（上升或下降）数据被采样
	SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;		                // NSS信号由硬件（NSS管脚）还是软件（使用SSI位）管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;         // 定义波特率预分频的值:波特率预分频值为8, 72/16=4.5M
	SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;                 // 指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial     = 7;		                        // CRC值计算的多项式
	SPI_Init(FLASH_SPIx , &SPI_InitStructure);  			                    // 根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
    
	SPI_Cmd(FLASH_SPIx , ENABLE); 	                                            // 使能SPI外设
    
    GPIO_SetBits(FLASH_SPI_SCK_PORT,  FLASH_SPI_SCK_PIN );
    GPIO_SetBits(FLASH_SPI_MISO_PORT, FLASH_SPI_MISO_PIN);
    GPIO_SetBits(FLASH_SPI_MOSI_PORT, FLASH_SPI_MOSI_PIN);    
}

void SPI2_Deconfig(void)
{
}

uint8_t SPI2_WR_Bytes(SPI_TypeDef* SPIx, uint8_t *pdata, uint16_t len)
{
    
}

/*******************************************************************************
* Function Name  : SPI1_Init
* Description    : SPI1时钟、端口初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;
 
    /* 使能SPI时钟         */
    NFC_SPI_APBxPeriphClockCmd(NFC_SPI_CLK, ENABLE);
    
    /* 使能SPI引脚相关时钟 */
    NFC_SPI_CS_APBxPeriphClockCmd(NFC_SPI_CS_CLK,    ENABLE);
    NFC_SPI_SCK_APBxPeriphClockCmd(NFC_SPI_SCK_CLK,  ENABLE);
    NFC_SPI_MISO_APBxPeriphClockCmd(NFC_SPI_MISO_CLK,ENABLE);
    NFC_SPI_MOSI_APBxPeriphClockCmd(NFC_SPI_MOSI_CLK,ENABLE);
    
    /* 配置SPI的 CS引脚，普通IO即可 */
    GPIO_InitStructure.GPIO_Pin   = NFC_SPI_CS_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init(NFC_SPI_CS_PORT, &GPIO_InitStructure);    

    /* 配置SPI的 SCK引脚*/
    GPIO_InitStructure.GPIO_Pin  = NFC_SPI_SCK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(NFC_SPI_SCK_PORT, &GPIO_InitStructure);

    /* 配置SPI的 MISO引脚*/
    GPIO_InitStructure.GPIO_Pin  = NFC_SPI_MISO_PIN;
    GPIO_Init(NFC_SPI_MISO_PORT, &GPIO_InitStructure);

    /* 配置SPI的 MOSI引脚*/
    GPIO_InitStructure.GPIO_Pin  = NFC_SPI_MOSI_PIN;
    GPIO_Init(NFC_SPI_MOSI_PORT, &GPIO_InitStructure);

    /* 停止信号: CS引脚高电平*/
    NFC_SPI_CS_HIGH();
  
	/* SPI的基本配置 */
	SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;  // 设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;	                // 设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize          = SPI_DataSize_8b;                  // 设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL              = SPI_CPOL_High;		            // 串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA              = SPI_CPHA_2Edge;	                // 串行同步时钟的第二个跳变沿（上升或下降）数据被采样
	SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;		                // NSS信号由硬件（NSS管脚）还是软件（使用SSI位）管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;        // 定义波特率预分频的值:波特率预分频值为8, 72/128=0.5625M
	SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;                 // 指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial     = 7;		                        // CRC值计算的多项式
	SPI_Init(NFC_SPIx , &SPI_InitStructure);  			                        // 根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
    
	SPI_Cmd(NFC_SPIx , ENABLE); 	                                            // 使能SPI外设
    
    GPIO_SetBits(NFC_SPI_SCK_PORT,  NFC_SPI_SCK_PIN );
    GPIO_SetBits(NFC_SPI_MISO_PORT, NFC_SPI_MISO_PIN);
    GPIO_SetBits(NFC_SPI_MOSI_PORT, NFC_SPI_MOSI_PIN);
}

/*******************************************************************************
* Function Name  : SPI1_WriteByte
* Description    : SPI发送一个字节
* Input          : SPIx-SPI设备, TxData-发送数据
* Output         : None
* Return         : None
*******************************************************************************/
void SPI1_WriteByte(SPI_TypeDef* SPIx,uint16_t TxData)
{
    uint8_t timeout=0;
    
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)       //检查发送是否完成 
    {
        if(++timeout>=SPI_WAIT_TIMEOUT) break;
    }
    SPI_I2S_SendData(SPIx,TxData);
}

/*******************************************************************************
* Function Name  : SPI1_ReadByte
* Description    : SPI读取数据
* Input          : SPIx-SPI设备, TxData-发送数据
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t SPI1_ReadByte(SPI_TypeDef* SPIx)
{
    uint8_t timeout=0;
    
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET)    //检查接收标志位
    {
        if(++timeout>SPI_WAIT_TIMEOUT) break;
    }
    return(SPI_I2S_ReceiveData(SPIx));
}

/*******************************************************************************
* Function Name  : 
* Description    : 
* Input          : 
* Output         : None
* Return         : None
*******************************************************************************/
uint8_t SPI_ReadWriteByte(SPI_TypeDef* SPIx, uint16_t data)
{
    uint8_t timeout=0;
    
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)
    {
        if(++timeout>SPI_WAIT_TIMEOUT) return 0xFF;
    }
    SPI1_WriteByte(SPIx, data);
    timeout=0;
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET)
    {
        if(++timeout>SPI_WAIT_TIMEOUT) return 0xFF;
    }
    return SPI1_ReadByte(SPIx);
}

/*******************************************************************************
* Function Name  : 
* Description    : 
* Input          : 
* Output         : None
* Return         : None
*******************************************************************************/
uint8_t DEV_ReadSR(uint8_t sr)
{
    uint8_t byte = 0;
    
    NFC_SPI_CS_LOW();                           //使能器件
    SPI_ReadWriteByte(NFC_SPIx, sr);            //发送读取状态寄存器命令
    byte = SPI_ReadWriteByte(NFC_SPIx, 0Xff);   //读取一个字节
    NFC_SPI_CS_HIGH();                          //取消片选
    
    return byte;
}

/*******************************************************************************
* Function Name  : 
* Description    : 
* Input          : 
* Output         : None
* Return         : None
*******************************************************************************/
void DEV_WriteSR(uint8_t sr, uint8_t value)
{
    NFC_SPI_CS_LOW();                           //使能器件
    SPI_ReadWriteByte(NFC_SPIx, sr);            //发送读取状态寄存器命令
    SPI_ReadWriteByte(NFC_SPIx, value);
    NFC_SPI_CS_HIGH();                          //取消片选
}

void _ASSERT_SPI_CLK_LOW(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    /*!< SPI_CS_GPIO, SPI_MOSI_GPIO, SPI_MISO_GPIO,
         and SPI_SCK_GPIO Periph clock enable */
    RCC_AHBPeriphClockCmd(GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7, ENABLE);

    /*!< Configure SPI pins: SCK */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);    
}

void _RELEASE_SPI_CLK_LOW(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    /*!< SPI_CS_GPIO, SPI_MOSI_GPIO, SPI_MISO_GPIO,
         and SPI_SCK_GPIO Periph clock enable */
    RCC_AHBPeriphClockCmd(GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7, ENABLE);

    /*!< Configure SPI pins: SCK */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;//GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_ResetBits(GPIOA, GPIO_Pin_5);    
}
